GNU/Linux常用端口操作設(shè)計(jì)與應(yīng)用
關(guān)鍵詞:GNU/Linux;串口通訊;并口I/O操作;usb存儲設(shè)備 中圖分類號:Tll 文獻(xiàn)標(biāo)識碼:A The Applications of the General I/O in the GNU/Linux LIU Yang,ZHOU Chun-jie (Department of Control Science and Engineering, HuaZhong University of Science & Technology, WuHan 430074, China) Abstract: This paper introduced the detailed operations of three kinds of the general I/O in the GNU/ Linux on the x86 platform, which are the serial communication, the standard parallel ports and the usb mass- storage devices. Key words: GNLT/Linux; serial communication; parallel ports; usb mass - storage 1 引言 GNU/Linux是一個(gè)開放源代碼,通用的,符合 POSIX(IEEE Standard Portable Operating System Interface for Computer Environment)標(biāo)準(zhǔn)的操作系統(tǒng)。其健壯、穩(wěn)定、功能強(qiáng)大的特點(diǎn),在服務(wù)器領(lǐng)域與嵌入式設(shè)備上極為流行。在通常的PCx86體系下,常用的標(biāo)準(zhǔn)I/O操作有三種:串口,并口、USB口與網(wǎng)口。GNU/Linux作為一種類UNIX系統(tǒng)繼承了UNIX的傳統(tǒng),將所有I/0操作都作為一種特殊的文件操作,程序員只需用通常的open()、 read()、write()、ioctl()、close()等函數(shù)就可以完成大部分的操作,大大減輕了軟件開發(fā)的難度,提高了開發(fā)的效率與可靠性,而這些I/O、的組合使用又基本可以滿足大部分系統(tǒng)的應(yīng)用。本文以一個(gè)實(shí)際系統(tǒng)為例,說明了基于PCx86體系下的串口、并口與USB口操作,網(wǎng)口由于其本身的特殊性,在本文就不作為一般的I/O介紹了。系統(tǒng)硬件示意圖如下,主控板為一塊586級的嵌入式主板PCM一5820,主頻為300Mhz、外擴(kuò)128Mb內(nèi)存、16M電子盤,主控板自帶兩個(gè)串口,一個(gè)標(biāo)準(zhǔn)25針并口,兩個(gè)USB口等接口;需要完成的功能有:與下層的一塊51為核心的按鍵顯示板通訊,讀入鍵值與刷新顯示;同時(shí)還需每10ms采集8路開關(guān)量輸入,通過一定的程序處理后輸出1路開關(guān)量;并不定期對采集的數(shù)據(jù)記錄做備份。實(shí)際系統(tǒng)正常工作時(shí),實(shí)現(xiàn)長時(shí)間無人值守與可靠運(yùn)行,本身要求有較高的穩(wěn)定性。本文將從串口、并口、USB口三個(gè)方面介紹。
2 串口通訊實(shí)現(xiàn) 根據(jù)按鍵顯示板本身對通訊要求,具有一定的偶發(fā)性和要求有交互性,我們利用主控板上的串口選用RS232的通訊方式。由于在Linux下,串口一般作為一個(gè)終端接口,即tty接口,POSIX.1定義了一個(gè)查詢和操作終端的標(biāo)準(zhǔn)接口,該接口被稱作 termios,在系統(tǒng)的頭文件
中定義。 termios是一個(gè)數(shù)據(jù)結(jié)構(gòu)和一系列操作這些數(shù)據(jù)結(jié)構(gòu)的函數(shù)。 #include struct termios{ tcflag-t c-iflag;/*指明輸入方式的標(biāo)志位*/ tcflag-t c-oflag;/*指明輸出方式的標(biāo)志位*/ tcflag-t c-cflag;/*指明控制方式的標(biāo)志位*/ tcflag-t c-lflag;/*指明局部方式的標(biāo)志位*/ cc-t c-line;/*指明分行定義*/ cc-t C-CC[NCCS];/*指明用于控制的特殊字符*/ speed-t c-ispeed;/*指明輸入傳輸速度*/ speed-t c-ospeed;/*指明輸出傳輸速度*/ } 對終端訪問的控制函數(shù)如下: 這些函數(shù)一起共構(gòu)成了通用的終端界面,提供對終端的有效控制操作,使得系統(tǒng)具有復(fù)雜的異步串口設(shè)備處理能力[4]。 RS232C只是一個(gè)物理層接口,為了保障數(shù)據(jù)傳輸?shù)臏?zhǔn)確性與可靠性,須用戶自己保證數(shù)據(jù)傳輸正確,根據(jù)本系統(tǒng)通訊的特點(diǎn):如果發(fā)生通訊,每次主機(jī)只會從按鍵顯示板接收到一幀包含按鍵信息的數(shù)據(jù),而每次按鍵都是獨(dú)立事件;主控板向鍵盤顯示板發(fā)送一定數(shù)據(jù)更新顯示。按照此需求,定義通訊協(xié)議如下:接收時(shí),每幀數(shù)據(jù)長度為5字節(jié),發(fā)送時(shí),每幀數(shù)據(jù)長度為12字節(jié),波特率為9600B/s,1位停止位,8位數(shù)據(jù)位,不帶奇偶校驗(yàn)。發(fā)送與接收的幀格式都是一樣的,幀首字節(jié)固定為0x55,第二個(gè)字節(jié)是本幀數(shù)據(jù)長度,最末兩字節(jié)為校驗(yàn)和,其余為數(shù)據(jù);緊跟著兩個(gè)相鄰數(shù)據(jù)包之間沒有關(guān)系,不需要幀序號,同時(shí)兩板之間距離很近,干擾源較少,因此誤碼率很低,用和校驗(yàn)就可保證傳輸?shù)恼`碼率。具體設(shè)計(jì)實(shí)現(xiàn)如下: 具體設(shè)計(jì)時(shí)為了保證一定的系統(tǒng)響應(yīng)速度,同時(shí)盡量減少主控板系統(tǒng)資源的使用,使用Linux下的信號驅(qū)動機(jī)制,使用SIGIO信號,當(dāng)有下位機(jī)傳按鍵至主控板時(shí),操作系統(tǒng)發(fā)出一個(gè)信號,用戶程序進(jìn)入信號處理程序。初始化串口時(shí),調(diào)用open()函數(shù),打開設(shè)備文件ttyS0,發(fā)送和接收數(shù)據(jù)時(shí)就可以直接使用read()和write()函數(shù),類似文件一樣使用串口。 3 并口操作實(shí)現(xiàn) 并口,有時(shí)也稱打印口,最初設(shè)計(jì)用于連接計(jì)算機(jī)和打印機(jī)。許多年后,其他很多設(shè)備也通過并口與計(jì)算機(jī)進(jìn)行連接,例如掃描儀、可移動設(shè)備和復(fù)制保護(hù)設(shè)備等?,F(xiàn)代PC上,并口有8根雙向數(shù)據(jù)線、四根雙向控制線以及5根狀態(tài)輸入線,他們通過一個(gè)DB一25凹口連接器供外部進(jìn)行訪問。從并口發(fā)明之初到現(xiàn)在,共發(fā)展出4種類型,實(shí)際系統(tǒng)中,主板的bios可以設(shè)置并口類型,本系統(tǒng)將主控板設(shè)為標(biāo)準(zhǔn)并口類型(SPP)。 在GNU/Linux下,一般對于PC并口進(jìn)行數(shù)據(jù)采集和控制有3種方法。第一種方法使用端口 I/O,簡單、操作性強(qiáng),并且可以清楚說明編寫設(shè)備驅(qū)動程序開發(fā)所必需的底層硬件控制過程。第二種方法使用Linux并口設(shè)備驅(qū)動程序ppdev來控制并口。這種方法與通過使用設(shè)備驅(qū)動程序及 ioctl系統(tǒng)調(diào)用進(jìn)行串口控制的方法相似。第三種方法創(chuàng)建自己訂制的并口驅(qū)動程序,這個(gè)并口驅(qū)動 程序使用/proc目錄。本系統(tǒng)要求達(dá)到每10ms采集一次開關(guān)量的要求,并根據(jù)運(yùn)算結(jié)果,輸出一個(gè)開關(guān)量;可以利用并口中的pin2 - pin9數(shù)據(jù)口,一次將8個(gè)開關(guān)量全部采集,并通過程序判斷,輸出結(jié)果至pin1口。采用第一種方法就能滿足本系統(tǒng)的要求,因此具體實(shí)現(xiàn)如下: 在Linux中有一個(gè)用于輸入的命令inb(ad— dress)和一個(gè)用于輸出的命令outb(value,address)。 C語言的宏擴(kuò)展實(shí)現(xiàn)了這兩個(gè)函數(shù),而且不涉及任何函數(shù)庫,但使用這兩個(gè)函數(shù)需要一些額外的函數(shù),函數(shù)ioperm()從內(nèi)核中申請和釋放端口訪問權(quán)[7]。 向并口寫入一個(gè)字節(jié)代碼如下: if(ioperm(0x378,3,1) ) exit (1); outb ( LP-DATA, 0x378); if( ioperm(0X378,3,0 )) exit(1); 從并口讀人一個(gè)字節(jié)代碼如下: if(ioperm(Ox378,3,1)) exit(1); putc(inb(Ox378) ); if( ioperm(OX378,3,0)) exit (1); 只要在上述代碼增加少量代碼就可以作為一個(gè)完整的代碼。這種方法也有缺點(diǎn),只有root用戶才能調(diào)用ioperm函數(shù),這會影響沒有root權(quán)限的用戶使用該程序,而且如果用戶想使用除了數(shù)據(jù)位以外的控制位作為輸出或輸入信號鎖存輸出值時(shí),則會帶來很大困難,另外,這樣的程序?qū)崿F(xiàn)可重入,將會面臨很大難度。但在本系統(tǒng)中,由于正式系統(tǒng)不存在用戶登錄的問題,同時(shí),并口只會被本進(jìn)程使用,不存在重入的問題。 為了保證每10ms的讀一次并口,利用Linux系統(tǒng)中的信號機(jī)制,使用settimer()函數(shù),每10ms產(chǎn)生一次SIGALRM信號,在這個(gè)信號的中斷函數(shù)里,采集一次開關(guān)量。保證了系統(tǒng)的實(shí)時(shí)性T4。 4 USB口用于數(shù)據(jù)備份具體實(shí)現(xiàn) 由于系統(tǒng)是24小時(shí)不停機(jī)的長時(shí)間運(yùn)行,本身采集的數(shù)據(jù)量是比較大的,可是主控板本身的存儲空間很小,而現(xiàn)場不具備安裝網(wǎng)線的條件,所以需要考慮一種盡可能不增加硬件投資,又可以獲得高可靠性,同時(shí)考慮到數(shù)據(jù)量比較大,對傳輸速率要求比較高,一般的串口已經(jīng)無法滿足要求,因此,采用USB的傳輸方案,利用u盤將現(xiàn)場的數(shù)據(jù)暫存,回到控制中心,再將數(shù)據(jù)倒入數(shù)據(jù)庫。另外,為了減少工作人員的工作量,利用Linux本身特有的 RAMDISK功能,將內(nèi)存中分出70Mb作為暫存區(qū),并將這部分作為系統(tǒng)的另一個(gè)分區(qū),在系統(tǒng)啟動的時(shí)候,直接掛載到系統(tǒng)中。 對于2.4.x的內(nèi)核來說,USB存儲設(shè)備驅(qū)動已經(jīng)集成在內(nèi)核里,但驅(qū)動程序只與Linux SCSI層交互。這意味著,在配置內(nèi)核時(shí),除了配置USB選項(xiàng)之外,還需要配置某些SCSI選項(xiàng),選擇支持合適的文件系統(tǒng)。在內(nèi)核已支持USB存儲設(shè)備的情況下,當(dāng)USB設(shè)備接人系統(tǒng)的USB口后,直接使用外部命令mount和umount的命令就可以將 USB存儲設(shè)備掛載到系統(tǒng)和解除掛載了。用cp等外部命令就可以將需要備份的數(shù)據(jù)從暫存區(qū)移動至USB存儲設(shè)備中。在程序中,使用system函數(shù)可以完成對外部命令程序的調(diào)用。具體實(shí)現(xiàn)過程如下: 1、檢測外部USB設(shè)備是否掛載到系統(tǒng)上,檢查/proc/bus/usb/deviees文件,是否已經(jīng)正確掛載上去,其次,根據(jù)/proc/scsi/目錄中設(shè)備文件的內(nèi)容,生成mount命令的第一個(gè)參數(shù);2、用system函數(shù)調(diào)用mount命令,將USB存儲設(shè)備掛載至文件系統(tǒng)節(jié)點(diǎn)/mnt下; 3、用system函數(shù)調(diào)用cp命令,將ramdisk中的內(nèi)容拷貝到該目錄下; 4、用system函數(shù)調(diào)用umount命令,將移動介質(zhì)卸載調(diào)。 5 總結(jié) 系統(tǒng)已經(jīng)在現(xiàn)場運(yùn)行了半年,從運(yùn)行的效果來看,串口通訊采用IO信號驅(qū)動的方式完全可以適應(yīng)其偶發(fā)性與一定的實(shí)時(shí)性,并口經(jīng)常作為IO數(shù)據(jù)的采集與輸出,采用定時(shí)掃描,而linux2.4.26操作系統(tǒng)的最小時(shí)間間隙100Hz,保證了每10ms采集一次的要求;USB口由于其傳輸數(shù)據(jù)量大、可靠,作為大數(shù)據(jù)量與交換,在Linux下,所有u盤和活動硬盤必須遵循USB mass—storage協(xié)議才能穩(wěn)定可靠運(yùn)行。另外,針對不同的硬件應(yīng)該制作不同的Linux內(nèi)核,充分利用內(nèi)核的模塊化,使用最少模塊的內(nèi)核,完成盡可能多的任務(wù)?,F(xiàn)在系統(tǒng)已經(jīng)開始實(shí)際運(yùn)行,從運(yùn)行的效果來開,所有的指標(biāo)都可以滿足當(dāng)初的設(shè)計(jì)要求,本身Linux系統(tǒng)的穩(wěn)定性,完全可以實(shí)現(xiàn)無人值守。 參考文獻(xiàn) [1] (美)Kurt Wall等.張輝譯.GNU/Linx編程指南(第二版)[M].北京:清華
查看更多評論